package com.wx.sign;

import com.wx.Base64Utils;

import javax.crypto.Cipher;
import java.io.ByteArrayOutputStream;
import java.security.*;
import java.security.interfaces.RSAPrivateKey;
import java.security.interfaces.RSAPublicKey;
import java.security.spec.PKCS8EncodedKeySpec;
import java.security.spec.X509EncodedKeySpec;
import java.util.HashMap;
import java.util.Map;

public class RSAUtils {
    private final static String RSA_ALGORITHM = "RSA";
    private final static String RSA_PUBLIC_KEY = "RSAPublicKey";
    private final static String RSA_PRIVATE_KEY = "RSAPrivateKey";
    static String  PUBLICKEY = "MFwwDQYJKoZIhvcNAQEBBQADSwAwSAJBAJNyGpwXu+iN158lNzZxvQnuhJKwuoisgINUmV/EYRbC6UevLq65/xbzirzHuieCngDwMtzxzHFm1Z6Yv7z8fQ8CAwEAAQ==";
    static String  PRIVATEKEY = "MIIBVAIBADANBgkqhkiG9w0BAQEFAASCAT4wggE6AgEAAkEAk3IanBe76I3XnyU3NnG9Ce6EkrC6iKyAg1SZX8RhFsLpR68urrn/FvOKvMe6J4KeAPAy3PHMcWbVnpi/vPx9DwIDAQABAkBVgivqcF06beApXFTbzzRZaSkbRUC4eIoDH/Hety2zG6vpBiKf5yImIrOVuxl5tkKGVVSX18bVAgcwgmM1i9PhAiEA5VFFcyiJaLopgrOm8o3Za0sTb92ziUV6Znd24XfiEnECIQCkmhnudWLXYSC/Vdy1U+wboxBzglDGJZRfIcl+CDhHfwIgLKB+VYTkCN+ByI/Rw45ba4f2xmRs1iARS/OfzQ0Zj+ECIER1Vx2nMsGzQsRxOIct7UAdVMVFyMRwcsISMlQ5pPaPAiEAqK5tUiCtnnDcCDrKhrvblZcB3/+rbri5TPwHtusX1bw=";


    public static Map<String, Object> getKey() throws NoSuchAlgorithmException {
        // 因为只存公钥和私钥，所以指明Map的长度是2
        Map<String, Object> keyMap = new HashMap<String, Object>(2);

        // 获取RSA算法实例
        KeyPairGenerator keyPairGen = KeyPairGenerator.getInstance(RSA_ALGORITHM);

        // 1024代表密钥二进制位数
        keyPairGen.initialize(1024);

        // 产生KeyPair工厂
        KeyPair keyPair = keyPairGen.generateKeyPair();
        RSAPublicKey publicKey = (RSAPublicKey) keyPair.getPublic();
        RSAPrivateKey privateKey = (RSAPrivateKey) keyPair.getPrivate();

        keyMap.put(RSA_PUBLIC_KEY, publicKey);
        keyMap.put(RSA_PRIVATE_KEY, privateKey);

        return keyMap;
    }


    /**
     * 使用公钥对数据进行加密
     */
    public static byte[] encryptPublicKey(byte[] binaryData, String publicKey) throws Exception {
        byte[] keyBytes = Base64Utils.decode(publicKey);
        X509EncodedKeySpec keySpec = new X509EncodedKeySpec(keyBytes);

        // 获取RSA算法实例
        KeyFactory keyFactory = KeyFactory.getInstance(RSA_ALGORITHM);
        Key pubKey = keyFactory.generatePublic(keySpec);

        // 初始化加密器
        Cipher cipher = Cipher.getInstance(keyFactory.getAlgorithm());
        cipher.init(Cipher.ENCRYPT_MODE, pubKey);

        SecureRandom random = new SecureRandom();
        if (binaryData.length > 53) {
            ByteArrayOutputStream baos = new ByteArrayOutputStream();
            byte[] segment = new byte[53];
            for (int idx = 0; idx < binaryData.length; idx += 53) {
                int remain = binaryData.length - idx;
                int segsize = Math.min(remain, 53);
                System.arraycopy(binaryData, idx, segment, 0, segsize);
                baos.write(cipher.doFinal(segment, 0, segsize));
            }

            return baos.toByteArray();
        } else {
            return cipher.doFinal(binaryData);
        }
    }
    /**
     * 使用私钥对数据进行解密
     */
    public static byte[] decryptPrivateKey(byte[] binaryData, String privateKey) throws Exception {
        byte[] keyBytes = Base64Utils.decode(privateKey);
        PKCS8EncodedKeySpec keySpec = new PKCS8EncodedKeySpec(keyBytes);

        // 获取RSA算法实例
        KeyFactory keyFactory = KeyFactory.getInstance(RSA_ALGORITHM);
        Key priKey = keyFactory.generatePrivate(keySpec);

        // 初始化加密器
        Cipher cipher = Cipher.getInstance(keyFactory.getAlgorithm());
        cipher.init(Cipher.DECRYPT_MODE, priKey);
        return cipher.doFinal(binaryData);
    }

    public static void main(String[] args) throws Exception {
        String mixStr = "abcd王ddf{}好人一个appName:七八个大壁咚，你说很补狠appinfo test ggheiheihaha者是一个测试盈利";
        String oneWord = "aaaaabbbbbbccccdddddddssssssssssssssssssssss";
        String repeatStr = "this is bob , this is bob , this is bob , this is bob , this is bob , this is bob , this is bob , this is bob , this is bob , this is bob , this is bob , this is bob , this is bob , this is bob , this is bob , this is bob , this is bob , ha";
        String repeatStrLong = "this is bob , this is bob , this is bob , this is bob , this is bob , this is bob , this is bob , this is bob , this is bob , this is bob , this is bob , this is bob , this is bob , this is bob , this is bob , this is bob , this is bob ,this is bob , this is bob , this is bob , this is bob , this is bob , this is bob , this is bob , this is bob , this is bob , this is bob , this is bob , this is bob , this is bob , this is bob , this is bob , this is bob , this is bob , ha";

//        byte[] encryptStr = encryptPublicKey(mixStr.getBytes(), PUBLICKEY);
//        byte[] encryptStr1 = encryptPublicKey(oneWord.getBytes(), PUBLICKEY);
//        byte[] encryptStr2 = encryptPublicKey(repeatStr.getBytes(), PUBLICKEY);
//        byte[] encryptStr3 = encryptPublicKey(repeatStrLong.getBytes(), PUBLICKEY);
//        System.out.println("before:" + mixStr.getBytes().length + " encrypt:" + encryptStr.length);
//        System.out.println("before:" + oneWord.getBytes().length + " encrypt:" + encryptStr1.length);
//        System.out.println("before:" + repeatStr.getBytes().length + " encrypt:" + encryptStr2.length);
//        System.out.println("before:" + repeatStrLong.getBytes().length + " encrypt:" + encryptStr3.length);
//        System.out.println("encrypt str:" + Base64Utils.encode(encryptStr4));
    }

    private static String getPrivateKey(Object privateKey) throws Exception {
        RSAPrivateKey rsaPrivateKey = (RSAPrivateKey) privateKey;
        return Base64Utils.encode(rsaPrivateKey.getEncoded());
    }

    private static String getPublicKey(Object pubKey) throws Exception {
        RSAPublicKey rsaPublicKey = (RSAPublicKey) pubKey;
        return Base64Utils.encode(rsaPublicKey.getEncoded());
    }
}
